package com.pervasa.demo.kitsample.impl;

import java.util.Vector;

public abstract class EventTree {
	public EventTree()
	{
		
	}
	
	public static class NoChildrenException extends Exception
	{
		
	}
	
	public enum TRUTH {
	    TRUE, FALSE, UNKNOWN 
	}
	
	public abstract TRUTH evaluate() throws NoChildrenException;

	public static EventTree parse(String exp, AtlasReactiveEngine ksa) throws Exception {
		if (exp.indexOf("+") != -1)
		{
			CompositeEvent ce = new CompositeEvent(CompositeEvent.orOp);
			String operands[] = exp.split("\\+");
			for (String operand : operands)
			{
				ce.getChildren().add(parse(operand, ksa));
			}
			return ce;
		}
		else if (exp.indexOf("*") != -1)
		{
			CompositeEvent ce = new CompositeEvent(CompositeEvent.andOp);
			String operands[] = exp.split("\\*");
			boolean isRightChild = false;
			for (String operand : operands)
			{
				if (operand.matches("^\\d+$"))
				{
					if (ce.getChildren().size() == 0)
					{
						throw new Exception("No tree node before *seconds* : " + exp);
					}
					//TODO: match for event*seconds*event
					EventTree old = ce.getChildren().get(ce.getChildren().size() - 1);
					
					EventTree newTree = new EventBefore(old, null, Integer.parseInt(operand));
					ce.getChildren().set(ce.getChildren().size() - 1, newTree);
					isRightChild = true;
				}
				else if (isRightChild)
				{
					EventBefore old = (EventBefore)ce.getChildren().get(ce.getChildren().size() - 1);
					old.rchild = parse(operand, ksa);
					isRightChild = false;
				}
				else
					ce.getChildren().add(parse(operand, ksa));
			}
			if (isRightChild)
			{
				throw new Exception("No tree node after *seconds* : " + exp);
			}
			return ce;
		}
		else
		{
			if (ksa.getEventTreeList().containsKey(exp))
				return ksa.getEventTreeList().get(exp);
			else
				return new TerminalEvent(exp, ksa.getDataHistoryManager());
		}
	}
	
	public static Vector<TerminalEvent> getTerminalEvents(EventTree root)
	{
		Vector<TerminalEvent> tevents = new Vector<TerminalEvent>();
		addTerminalEvents(root, tevents);
		return tevents;
	}

	private static void addTerminalEvents(EventTree node,
			Vector<TerminalEvent> tevents) {
		if (node instanceof TerminalEvent)
		{
			TerminalEvent te = (TerminalEvent)node;
			tevents.add(te);
			return;
		}
		else if (node instanceof EventBefore)
		{
			//I don't want anything from children of EventBefore
			return;
		}
		else if (node instanceof CompositeEvent)
		{
			CompositeEvent ce = (CompositeEvent)node;
			for (int i = 0; i < ce.getChildren().size(); i++)
			{
				addTerminalEvents(ce.getChildren().get(i), tevents);
			}
			return;
		}
	}
}